#!/usr/bin/python    
#encoding=utf-8 

import json  
import struct
import socket
import sys
#from socket import *
import thread
import hashlib
import time
from app.service.door.services.error_code import ERROR_CODE
import urllib2
import math
import fcntl 
#imds
IMDS_HOST="http://127.0.0.1"
IMDS_PATH="/cgi-bin/zfms.fcgi/local/attrs/"
#http://127.1.1.1/cgi-bin/zfms.fcgi/local/attrs/45.2?domain=alarm
#ApiKey
API_USERNAME="door"
API_USERPWD="door123"
#API_VALUE="4536135feb666a1b4bb42a10e376687c"

#MySQL
# MySQL_HOST='192.168.1.243'
# MySQL_PORT='3306' 
# MySQL_USER='root'
# MySQL_PASSWD='123456'
# MySQL_DB='door'

#Door 
DC_HOST='127.0.0.1'
DC_PORT=60000
DC_BUFSIZE=1024
DC_ADDR=(DC_HOST,DC_PORT) 

#Socket
SOCKET_TIMEOUT=10
SOCKET_TIMEOUT_MIN=1


#门禁事件对应的ciid
DC_ALARM_CIID='_S_dac'

#SOH
DC_HEADER_SOH='0x17'
#PT_Read
DC_HEADER_PT_R='0x94'
#MID
DC_HEADER_MID1='0x00'
DC_HEADER_MID2='0x32'
#SID
DC_HEADER_SID1='0x00'

DC_HEADER_SID=['0x01','0x02']

DC_HEADER_SID2='0x01'
DC_HEADER_SID2_2='0x02'

DC_DATA_STX='0x02'
DC_DATA_ETX='0x03'
#BCC
DC_BCC_CODE='0x20'

#配置send——messages str
DOOR_TYPE = '17'
DOOR_F_CODE = '94'
DOOR_FIXED = '00'
DOOR_SN = '00'
CARD_VALID_DATE='15110101019912312359'#默认日期，2015-11-01 01:01 到 2099-12-31 23:59

#获取公网ip
def get_ip_address(ifname): 
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    return socket.inet_ntoa(fcntl.ioctl( 
    s.fileno(), 
    0x8915, # SIOCGIFADDR 
    struct.pack('256s', ifname[:15]) 
    )[20:24]) 


#获取sn
def get_sn():
    url='http://127.0.0.1/cgi-bin/extmod/dac/devices'
    # url='http://192.168.1.10/cgi-bin/extmod/dac/devices'
    request = urllib2.Request(url)
    request.add_header('Content-Type', 'your/conntenttype')
    request.get_method = lambda:'GET'
    request = urllib2.urlopen(request)
    devices =  json.loads(request.read())
    for x in devices:
       sn = x["channel"]['addr']
    return  sn


#获取sn
def get_ip():
    url='http://127.0.0.1/cgi-bin/extmod/dac/devices'
    # url='http://192.168.1.10/cgi-bin/extmod/dac/devices'
    request = urllib2.Request(url)
    request.add_header('Content-Type', 'your/conntenttype')
    request.get_method = lambda:'GET'
    request = urllib2.urlopen(request)
    devices =  json.loads(request.read())
    for x in devices:
        datas =  x["channel"]['chid'].split(':')
    return  datas[0]


def Verify_ApiKey(apikey):
    sysApiKey=hashlib.md5(API_USERNAME + API_USERPWD).hexdigest()
    if apikey.lower() ==sysApiKey.lower():
	return True
    return False
  
def build_HEADER_String(fc):
    re=DC_HEADER_SOH + \
       DC_HEADER_PT_R + \
       DC_HEADER_MID1 + \
       DC_HEADER_MID1 + \
       fc

    return Repalce_0X(re)
def build_Send_String(fc,data,bcc,*sid2_2):
    if len(sid2_2)>0:
        tmp_SID2=DC_HEADER_SID2_2
    else:
        tmp_SID2=DC_HEADER_SID2

    re=DC_HEADER_SOH + \
       DC_HEADER_PT_R + \
       DC_HEADER_MID1 + \
       DC_HEADER_MID1 + \
       fc
    re = re + DC_DATA_STX + data + DC_DATA_ETX + str(bcc)
    return Repalce_0X(re)

def build_Send_String_Ex(fc,data,sid2,bcc):
    re=DC_HEADER_SOH + \
       DC_HEADER_PT_R + \
       DC_HEADER_MID1 + \
       DC_HEADER_MID2 + \
       DC_HEADER_SID1 + \
       sid2 + \
       fc
    re = re + DC_DATA_STX + data + DC_DATA_ETX + str(bcc)
    return Repalce_0X(re)

def Is_FF(sVal):
    sVal=str(sVal).upper()
    #print "sVal:{0}".format(sVal)
    if sVal =="FF":
	return True
    else:
	return False

def Is_Null(sVal):
    #print "sVal:{0}".format(sVal)
    #sVal=str(sVal)
    if type(sVal) == type(None):
	return True
    if sVal and str(sVal).strip()!="":
	#print "sval:false"
	return False
    else:
	#print "sval:true"
	return True
def Null2Def(sVal,tDef):
    #sVal=str(sVal)
    if type(sVal) == type(None):
	return tDef

    if sVal and str(sVal).strip()!="":
	return sVal
    else:
	return tDef

def Is_InList(obj,name):
    if name in obj:
	return True
    return False

def Is_InListDef(obj,name,tdef):
    if name in obj:
	return obj[name]

    return tdef

def Reverse_Card_No(cardNo):
    cardList=cardNo.decode('hex')
    #newList=[]
    newCardNo=""
    cnt = len(cardList)
    for i in range(cnt):
        #newList.append(cardList[cnt-i-1].encode('hex'))
	newCardNo=newCardNo+cardList[cnt-i-1].encode('hex')

    return newCardNo

def convert_Str2Hex(val):
    try:
    	return int(val,16)

    except CouchbaseError as e:
    	print "convert_Str2Hex Err:",e
   	raise

def Repalce_0X(data):
    return str(data).replace('0x','')

def Repalce_Colon(data):
    return str(data).replace(':','')

def build_HEADER_Code(fc):
    re=convert_Str2Hex(DC_HEADER_SOH) ^ \
       convert_Str2Hex(DC_HEADER_PT_R) ^ \
       convert_Str2Hex(DC_HEADER_MID1) ^ \
       convert_Str2Hex(DC_HEADER_MID2) ^ \
       convert_Str2Hex(DC_HEADER_SID1) ^ \
       convert_Str2Hex(DC_HEADER_SID2) ^ \
       convert_Str2Hex(fc)
    
    return re       

def build_CHKBCC_Code(headCode,data):
    re=headCode ^ convert_Str2Hex(DC_DATA_STX)

    if data.strip()!='':
	#ls=list(data.decode('hex'))
        #datas=data.strip().split()
	datas=data.decode('hex')
        if datas and len(datas)>0:
            for d in datas:
 		re=re ^ int(d.encode('hex'),16)
    
    re=re ^ convert_Str2Hex(DC_DATA_ETX) | convert_Str2Hex(DC_BCC_CODE)
    return hex(re)

def build_CHK_BCC(header,data):
    re=header ^ convert_Str2Hex(DC_DATA_STX)

    if data.strip()!='':
	ls=list(data.decode('hex'))
        datas=data.strip().split()
        if datas and len(datas)>0:
            for d in datas:
 		re=re ^ d
    
    re=re ^ convert_Str2Hex(DC_DATA_ETX) | convert_Str2Hex(DC_BCC_CODE)
    return hex(re)

def socket_Send(sock,send):
    sock.send(send)    

def socket_Start(send,*timout_min):
    re=""  

    tmp_timeout=SOCKET_TIMEOUT
    if len(timout_min)>0:
        tmp_timeout=SOCKET_TIMEOUT_MIN

    try:
        socket.setdefaulttimeout(tmp_timeout)
        client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

        #client.setdefaulttimeout(SOCKET_TIMEOUT)
        client.connect(DC_ADDR)
        #client.settimeout(None) 
  
        send=send.decode("hex")
        print send
        thread.start_new_thread(socket_Send,(client,send,))

        while True: 
            re=client.recv(DC_BUFSIZE)
	    if re:
	        break

        client.close()

        return re.encode("hex")
    except Exception as e:
        print "error:{0}".format(e)
        return ""


def socket_Send(sock,send,address):
    sock.sendto(send,address)    


# 拼装send 的消息
def  send_str(sn,_type):
    sn_all = desc_sn(sn)
    sn_str = ''.join([DOOR_TYPE,_type,DOOR_FIXED,DOOR_FIXED,sn_all])
    return sn_str

#拼装倒叙sn 并返回16进制str
def  desc_sn(sn):
    hexadecimal_sn = hex(int(sn))
    hexadecimal_sn_unset = Repalce_0X(hexadecimal_sn)
    sn_1 = hexadecimal_sn_unset[-2:]
    sn_2 = hexadecimal_sn_unset[-4:-2]
    sn_3 = hexadecimal_sn_unset[-6:-4]
    if len(hexadecimal_sn_unset)==7:
         sn_4 = '0'+hexadecimal_sn_unset[0:1]
    else:
         sn_4 = hexadecimal_sn_unset[0:2]
    sn_all = ''.join([sn_1,sn_2,sn_3,sn_4])
    return sn_all


#拼装卡号 并返回16进制str
def  card_str(sn):
    hexadecimal_sn = hex(int(sn))
    # hexadecimal_sn_unset = Repalce_0X(hexadecimal_sn)
    # c_1 = hex( int(sn[0:3]))
    # c_2 = hex( int(sn[3:5]))
    # c_3 = hex( int(sn[5:8]))
    # c_4 = hex( int(sn[8:9]))
    # c_1 = hex( int(sn[0:3]))
    # c_2 = hex( int(sn[3:5]))
    # c_3 = hex( int(sn[5:8]))
    # c_4 = hex( int(sn[8:9]))
    # print c_1,c_2,c_3,c_4
    # sn_all = ''.join([Repalce_0X(c_1).zfill(2),Repalce_0X(c_2).zfill(2),Repalce_0X(c_3).zfill(2),Repalce_0X(c_4).zfill(2)])
    sn_all  = Repalce_0X(hexadecimal_sn)
    return sn_all[0:8]


#拼装ip 并返回16进制str
def  ip_send_str(ip):
     ip_arr=ip.split('.')
     ip_fill_str=""
     for x in ip_arr:
        a = hex(int(x))
        _a = Repalce_0X(a)
        if len(_a)==1:
            _a = '0'+_a
        ip_fill_str =''.join([ip_fill_str,_a])
     return ip_fill_str

#拼装port 并返回16进制str
def  port_back_str(port):
    a = hex(int(port))
    _a = Repalce_0X(a)
    for x in xrange(1,len(_a)+1):
        p_1 = _a[2:4]
        p_2 = _a[0:2]
    port_fill_str =''.join([p_1,p_2])
    return port_fill_str

#固定str填充0
def  send_str_fill(_str):
    for x in xrange(1,128 + 1):
        if x>len(_str):
           _str = ''.join([_str,"00"])
    return _str

#解析str中的ip
def resolve_in_ip(re_str):
    for x in xrange(1,len(re_str) +1):
        if  x==16:
            _ip_1 = re_str[x]+re_str[x+1]
        elif x==18:
            _ip_2 = re_str[x]+re_str[x+1]
        elif x==20:
            _ip_3 = re_str[x]+re_str[x+1]
        elif x==22:
            _ip_4 = re_str[x]+re_str[x+1]
    _ip_101 = int(_ip_1, 16)
    _ip_102 = int(_ip_2, 16)
    _ip_103 = int(_ip_3, 16)
    _ip_104 = int(_ip_4, 16)
    res = '.'.join([str(_ip_101),str(_ip_102),str(_ip_103),str(_ip_104)])
    return res

#解析str中的卡号
def resolve_in_card(re_str):
    for x in xrange(1,len(re_str) +1):
        if  x==32:
            _ip_1 = re_str[x]+re_str[x+1]
        elif x==34:
            _ip_2 = re_str[x]+re_str[x+1]
        elif x==36:
            _ip_3 = re_str[x]+re_str[x+1]
        elif x==38:
            _ip_4 = re_str[x]+re_str[x+1]
    all_str = ''.join([str(_ip_1),str(_ip_2),str(_ip_3),str(_ip_4)])
    # _ip_101 = int(_ip_1, 16)
    # _ip_102 = int(_ip_2, 16)
    # _ip_103 = int(_ip_3, 16)
    # _ip_104 = int(_ip_4, 16)
    # res = ''.join([str(_ip_101),str(_ip_102),str(_ip_103),str(_ip_104)])
    # res = ''.join([str(_ip_104),str(_ip_103),str(_ip_102),str(_ip_101)])
    return int(all_str,16)

#event 解析content
def resolve_content(re_str):
    event_type_arr = ['无记录','刷卡','远程开门、按钮、设备启动','报警记录']
    door_arr = ['0','1门','2门','3门','4门']
    effective_arr = ["无效","有效"]
    entrance_door_arr = ["0","进门","出门"]
    for x in xrange(1,len(re_str) +1):
        if  x==24:
            event_type = re_str[x+1]
        elif x==26:
            is_effective = re_str[x+1]
        elif x==28:
            door_number = re_str[x+1]
        elif x==30:
            entrance_door = re_str[x+1]
        # elif x==32:
        #     _ip_1 = re_str[x]+re_str[x+1]
        # elif x==34:
        #     _ip_2 = re_str[x]+re_str[x+1]
        # elif x==36:
        #     _ip_3 = re_str[x]+re_str[x+1]
        # elif x==38:
        #     _ip_4 = re_str[x]+re_str[x+1]
        elif x==54:
            _explain = re_str[x]+re_str[x+1]
    # _ip_101 = int(_ip_1, 16)
    # _ip_102 = int(_ip_2, 16)
    # _ip_103 = int(_ip_3, 16)
    # _ip_104 = int(_ip_4, 16)
    _explain_back = int(_explain,16)
    # card_no = ''.join([str(_ip_101),str(_ip_102),str(_ip_103),str(_ip_104)])
    return event_type_arr[int(event_type)]+effective_arr[int(is_effective)]+"  "+door_arr[int(door_number)]+entrance_door_arr[int(entrance_door)]+" 说明："+ERROR_CODE[_explain_back]
    # return "1号门打开"

#解析门禁的状态以及故障信息
def resolve_in_status(re_str):
    for x in xrange(1,len(re_str) +1):
        if  x==28:
            _d_num = re_str[x]+re_str[x+1]
        elif  x==54:
            _vdes = re_str[x]+re_str[x+1]
        elif  x==56:
            _ip_1 = re_str[x]+re_str[x+1]
        elif x==58:
            _ip_2 = re_str[x]+re_str[x+1]
        elif x==60:
            _ip_3 = re_str[x]+re_str[x+1]
        elif x==62:
            _ip_4 = re_str[x]+re_str[x+1]
        elif x==64:
            _s_1 = re_str[x]+re_str[x+1]
        elif x==66:
            _s_2 = re_str[x]+re_str[x+1]
        elif x==68:
            _s_3 = re_str[x]+re_str[x+1]
        elif x==70:
            _s_4 = re_str[x]+re_str[x+1]
        elif x==72:
            _g = re_str[x]+re_str[x+1]
        elif x==98:
            _d_off_no = re_str[x]+re_str[x+1]
    # _ip_101 = int(_ip_1, 16)
    # _ip_102 = int(_ip_2, 16)
    # _ip_103 = int(_ip_3, 16)
    # _ip_104 = int(_ip_4, 16)
    # _s_101 = int(_s_1, 16)
    # _s_102 = int(_s_2, 16)
    # _s_103 = int(_s_3, 16)
    # _s_104 = int(_s_4, 16)
    _d_num = int(_d_num, 16)
    _vdes = int(_vdes, 16)
    _g = int(_g, 16)
    _d_off_no = int(_d_off_no, 16)
    # res = ','.join([str(_ip_101),str(_ip_102),str(_ip_103),str(_ip_104)])
    # res2 = ','.join([str(_s_101),str(_s_102),str(_s_103),str(_s_104)])
    # _back = {"id":"5.1","pv":0,"qul":0,"tm":time.time(),"vdes":"关门"}
    restul = {"_d_num":int(_d_num),"_vdes":_vdes,"_d_off_no":_d_off_no,"fault_num":_g}
    return restul


#将日期转换成BCD码   20存为 20 + (20/10)*6= 32=0x20   13存为 13 + (13/10)*6=19=0x13
def BCD_Str(_date):
   return str(_date).replace('-','')

#解析返回是否添加成功
def resolve_is_success(_str):
     for x in xrange(1,len(_str) +1):
         if  x==16:
            _status = _str[x]+_str[x+1]

     if _status == "01":
        return True
     else:
        return False

#发送udp 消息
def song_socket_Start(send,dc_ip,*timout_min):
    re=""  
    tmp_timeout=SOCKET_TIMEOUT
    if len(timout_min)>0:
        tmp_timeout=SOCKET_TIMEOUT_MIN
    try:
        socket.setdefaulttimeout(tmp_timeout)
        client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        send =send.decode("hex")
        # print "send=",send
        client.sendto(send,(dc_ip,DC_PORT))   

        while True: 
            re,addr=client.recvfrom(DC_BUFSIZE)
            if re:
                break
        client.close()
        return re.encode('hex')
    except Exception as e:
        print "error:{0}".format(e)
        return ""


def socket_Start_NotWait(send):
    re=""  
    
    try:
        socket.setdefaulttimeout(SOCKET_TIMEOUT2)
        client=socket.socket(socket.f,socket.SOCK_STREAM)

        client.connect(DC_ADDR)
  
        send=send.decode("hex")
 
        thread.start_new_thread(socket_Send,(client,send,))

        while True: 
            re=client.recv(DC_BUFSIZE)
	    if re:
	        break

        client.close()

        return re.encode("hex")
    except Exception as e:
	print "error:{0}".format(e)
	return ""

def Convert_EventType_Desc(event_type):
    et=str(event_type).lower()
    re_val=""
    if et=="41":
        re_val="正常刷卡"
    elif et=="42":
        re_val="正常开门"
    elif et=="43":
        re_val="非法刷卡"
    elif et=="45":
        re_val="非法开门"
    elif et=="47":
        re_val="消防报警"
    elif et=="48":
        re_val="防拆报警"
    elif et=="49":
        re_val="密码开门"
    elif et=="4a":
        re_val="正常刷卡"#"内读头正常刷卡"
    elif et=="4b":
        re_val="非法刷卡"#"内读头非法刷卡"
    elif et=="4d":
        re_val="出门开关"
    elif et=="4f":
        re_val="电脑远程开门"
    elif et=="50":
        re_val="门虚掩报警"
    elif et=="51":
        re_val="紧急按钮"

    return re_val

def Convert_EventType(event_type):
    et=str(event_type).lower()
    re_val=""
    if et=="41":
        re_val="record"
    elif et=="42":
        re_val="record"
    elif et=="43":
        re_val="record"
    elif et=="45":
        re_val="record"
    elif et=="47":
        re_val="alarm"
    elif et=="48":
        re_val="alarm"
    elif et=="49":
        re_val="record"
    elif et=="4a":
        re_val="record"
    elif et=="4b":
        re_val="record"
    elif et=="4d":
        re_val="record"
    elif et=="4f":
        re_val="record"
    elif et=="50":
        re_val="alarm"
    elif et=="51":
        re_val="record"

    return re_val

def Format_Validate(body):
    index_start=body.find('{')
    index_end=body.rfind('}')
	    
    if index_start==-1 or index_end==-1:
	return -1;
    return body[index_start:index_end+1]  

def NoRight_Result():
    data=build_API_Result("-2",ERROR_CODE[-2],{})
    return dumps_API_Result(data)

def InvalidFormat_Result():
    data=build_API_Result("-3",ERROR_CODE[-3],{})
    return dumps_API_Result(data)

def build_API_Result(code,msg,data):
    re={}
    re["error_code"]=code
    re["msg"]=msg
    re["data"]=data
    return re

def dumps_API_Result(data):
    return json.dumps(data,ensure_ascii=False)



